package com.third.device.mg.serialport.factory.forick.product

import com.third.device.mg.serialport.factory.forick.BaseForickProduct
import com.third.device.mg.serialport.utils.hexToBytes
import com.third.device.mg.serialport.utils.to2ByteH
import com.third.device.mg.serialport.utils.to2ByteL
import com.third.device.mg.serialport.utils.toZeroString

/**
 * company 广东玛格家居有限公司
 * @author smoker
 * @Date 2021/12/22
 * Description:弗雷克--三合一环境面板(空调面板)
 * 空调、地暖、新风 三合一控制环境面板
 * */
class PanelUART : BaseForickProduct() {
    companion object {
        //寄存器地址对应的功能清单 -- 2 byte
        //空调设备
        val HLR_ON_OFF_AIR = byteArrayOf(0x00, 0x01) //空调开关机功能
        val HLR_WORK_MODE_AIR  = byteArrayOf(0x00, 0x02) //空调工作模式
        val HLR_WIND_MODE_AIR  = byteArrayOf(0x00, 0x03) //空调风速设定
        val HLR_TEMP_AIR       = byteArrayOf(0x00, 0x04) //空调温度设定
        val HLR_VALVE_AIR      = byteArrayOf(0x00, 0x05) //空调阀控制

        //地暖设备
        val HLR_ON_OFF_FLOOR = byteArrayOf(0x00, 0x06) //地暖开关机功能
        val HLR_TEMP_FLOOR       = byteArrayOf(0x00, 0x07) //地暖温度设定
        val HLR_VALVE_FLOOR      = byteArrayOf(0x00, 0x08) //空调阀控制

        //新风设备
        val HLR_ON_OFF_WIND = byteArrayOf(0x00, 0x09) //新风开关机功能
        val HLR_PARAM_WIND      = byteArrayOf(0x00, 0x0A) //新风参数设定值(预留)
        val HLR_WIND_MODE_WIND  = byteArrayOf(0x00, 0x0B) //新风风速设定

        //环境参数
        val HLR_OFFSET_TEMP_ENVIRONMENT        = byteArrayOf(0x00, 0x0C) //环境：补偿温度
        val HLR_REAL_TIME_TEMP_ENVIRONMENT     = byteArrayOf(0x00, 0x0D) //环境：实时温度
        val HLR_REAL_TIME_HUMIDITY_ENVIRONMENT = byteArrayOf(0x00, 0x0E) //环境：实时湿度
        val HLR_REAL_TIME_PARAM_ENVIRONMENT    = byteArrayOf(0x00, 0x0F) //环境：新风实时参数

        //面板参数
        val HLR_RELAY_AIR_PANEL            = byteArrayOf(0x00, 0x10) //面板：空调继电器
        val HLR_RELAY_FLOOR_PANEL          = byteArrayOf(0x00, 0x11) //面板：地暖继电器
        val HLR_RELAY_WIND_PANEL           = byteArrayOf(0x00, 0x12) //面板：新风继电器
        val HLR_LOW_TEMP_DISC_PANEL        = byteArrayOf(0x00, 0x13) //面板：低温保护阀值
        val HLR_LOCK_PANEL                 = byteArrayOf(0x00, 0x14) //面板：是否锁定标志
        val HLR_LOCK_MODE_PANEL            = byteArrayOf(0x00, 0x15) //面板：全锁半锁标志配置
        val HLR_DATA_REPORT_PANEL          = byteArrayOf(0x00, 0x16) //面板：数据上报 主被动标志位
        val HLR_INDICATOR_LIGHTNESS_PANEL  = byteArrayOf(0x00, 0x17) //面板：指示灯亮度登记配置
        val HLR_LUX_LEVEL_PANEL            = byteArrayOf(0x00, 0x18) //面板：光照度等级
        val HLR_LIGHT_SLEEP_PANEL          = byteArrayOf(0x00, 0x19) //面板：背光休眠
        val HLR_VERSION_PANEL              = byteArrayOf(0x00, 0x1A) //面板：软件版本--只读

    }

    override fun productDescribe(): String = "弗雷克--三合一环境面板(空调面板)"

//***空调设备*********************************************************************************************************************
    /**
     * 空调开机/关机
     * @param onOff true:开机  false:关机
     */
    fun onOffAir(address: Byte, onOff: Boolean): ByteArray {
        val pushMsg = createSingleWriteCommand(address ,HLR_ON_OFF_AIR)
        val on =
            if (onOff) {
                1
            } else {
                0
            }
        val result = on.to2ByteH()
        System.arraycopy(result, 0, pushMsg, 4, result.size)
        return crcCheck(pushMsg)
    }


    /**
     * 切换空调模式
     * [mode]0:制冷 1:制热 2:除湿 3:送风
     */
    fun changeModeAir(address: Byte, mode: Int): ByteArray {
        val pushMsg = createSingleWriteCommand(address ,HLR_WORK_MODE_AIR)
        val result = mode.to2ByteH()
        System.arraycopy(result, 0, pushMsg, 4, result.size)
        return crcCheck(pushMsg)
    }

    /**
     * 切换空调风速
     * [mode]0:自动 1:低速 2:中速 3:高速
     *
     * 指令:（第一个字节:00表示手动 ，01表示自动 ）
     * 自动: 01 00
     * 低速: 00 01
     * 中速: 00 02
     * 高速: 00 03
     */
    fun changeWindModeAir(address: Byte, mode: Int): ByteArray {
        val pushMsg = createSingleWriteCommand(address ,HLR_WIND_MODE_AIR)
        // 1.to2ByteL() ==>> 01 00
        // 1.to2ByteH() ==>> 00 01
        val result = if (mode == 0){
            1.to2ByteL()
        }else{
            mode.to2ByteH()
        }
        System.arraycopy(result, 0, pushMsg, 4, result.size)
        return crcCheck(pushMsg)
    }


    /**
     * 设置空调的制冷/制热的温度
     * [temp] 16℃~30℃之间
     */
    fun setTemperatureAir(address: Byte, temp: Int): ByteArray {
        val pushMsg = createSingleWriteCommand(address ,HLR_TEMP_AIR)
        val result = temp.to2ByteH()
        System.arraycopy(result, 0, pushMsg, 4, result.size)
        return crcCheck(pushMsg)
    }

    /**
     * 读取空调当前的制冷温度
     */
    fun getTemperatureAir(address: Byte): ByteArray {
        val pushMsg = createSingleReadCommand(address ,HLR_TEMP_AIR)
        //position = 4/5 ，从第一个寄存器开始要查询的数量 ，这里默认查询一个
        val result = 1.to2ByteH()
        System.arraycopy(result, 0, pushMsg, 4, result.size)
        return crcCheck(pushMsg)
    }

    /**
     * 空调的 阀控制
     *
     * @param address  设备地址
     * @param type 阀的类型
     * 00:默认-无效
     * 01:一路双线阀
     * 02:一路三线阀
     * 03:两路双线阀
     * @param mode 阀的状态
     * 当[type] = 00 时,        [mode] 值:  00:无效,恢复默认 ;
     * 当[type] = 01 | 02 时,   [mode] 值:  00:阀关 ;        01:阀开
     * 当[type] = 03 时 ,       [mode] 值:  00:冷阀关 ;      01:冷阀开  ; 02:热阀关  ; 03:热阀开
     *
     * [0x0000] 默认-阀无效
     * [0x0100] 一路双线阀 关
     * [0x0101] 一路双线阀 开
     * [0x0200] 一路三线阀 关
     * [0x0201] 一路三线阀 开
     * [0x0300] 两路双线阀 冷阀关
     * [0x0301] 两路双线阀 冷阀开
     * [0x0302] 两路双线阀 热阀关
     * [0x0303] 两路双线阀 热阀开
     *
     */
    fun changeValveModeAir(address: Byte,type:Int,mode: Int):ByteArray{
        val pushMsg = createSingleWriteCommand(address ,HLR_VALVE_AIR)
        //小端排序 ，低位前，高位后
        val controlHex = "${mode.toZeroString()}${type.toZeroString()}"
        val control = controlHex.hexToBytes()
        pushMsg[4] = control[1]
        pushMsg[5] = control[0]
        return crcCheck(pushMsg)
    }



//***地暖设备*********************************************************************************************************************
    /**
     * 地暖设备开机/关机
     * @param onOff true:开机  false:关机
     */
    fun onOffFloor(address: Byte, onOff: Boolean):ByteArray{
        val pushMsg = createSingleWriteCommand(address ,HLR_ON_OFF_FLOOR)
        val on =
            if (onOff) {
                1
            } else {
                0
            }
        val result = on.to2ByteH()
        System.arraycopy(result, 0, pushMsg, 4, result.size)
        return crcCheck(pushMsg)
    }


    /**
     * 设置地暖的温度
     * [temp] 16℃~30℃之间
     */
    fun setTemperatureFloor(address: Byte, temp: Int): ByteArray {
        val pushMsg = createSingleWriteCommand(address ,HLR_TEMP_FLOOR)
        val result = temp.to2ByteH()
        System.arraycopy(result, 0, pushMsg, 4, result.size)
        return crcCheck(pushMsg)
    }


    /**
     * 地暖的 阀控制
     *
     * @param address  设备地址
     * @param type 阀的类型
     * 00:默认-无效
     * 01:一路双线阀
     * 02:一路三线阀
     * @param mode 阀的状态
     * 当[type] = 00 时,        [mode] 值:  00:无效,恢复默认 ;
     * 当[type] = 01 | 02 时,   [mode] 值:  00:阀关 ;        01:阀开
     *
     * [0x0000] 默认-阀无效
     * [0x0100] 一路双线阀 关
     * [0x0101] 一路双线阀 开
     * [0x0200] 一路三线阀 关
     * [0x0201] 一路三线阀 开
     *
     */
    fun changeValveModeFloor(address: Byte,type:Int,mode: Int):ByteArray{
        val pushMsg = createSingleWriteCommand(address ,HLR_VALVE_FLOOR)
        //小端排序 ，低位前，高位后
        val controlHex = "${mode.toZeroString()}${type.toZeroString()}"
        val control = controlHex.hexToBytes()
        pushMsg[4] = control[1]
        pushMsg[5] = control[0]
        return crcCheck(pushMsg)
    }


//***新风设备*********************************************************************************************************************
    /**
     * 新风设备开机/关机
     * @param onOff true:开机  false:关机
     */
    fun onOffWind(address: Byte, onOff: Boolean):ByteArray{
        val pushMsg = createSingleWriteCommand(address ,HLR_ON_OFF_WIND)
        val on =
            if (onOff) {
                1
            } else {
                0
            }
        val result = on.to2ByteH()
        System.arraycopy(result, 0, pushMsg, 4, result.size)
        return crcCheck(pushMsg)
    }


    /**
     * 切换新风风速
     * [mode]0:关闭 1:低速 2:中速 3:高速
     *  1.to2ByteL() ==>> 01 00
     *  1.to2ByteH() ==>> 00 01
     * 指令:（第一个字节:00表示手动 ，01表示自动 ）
     * 关闭: 00 00
     * 低速: 00 01
     * 中速: 00 02
     * 高速: 00 03
     */
    fun changeWindModeWind(address: Byte, mode: Int): ByteArray {
        val pushMsg = createSingleWriteCommand(address ,HLR_WIND_MODE_WIND)
        val result = mode.to2ByteH()
        System.arraycopy(result, 0, pushMsg, 4, result.size)
        return crcCheck(pushMsg)
    }

//***环境参数(被动)*********************************************************************************************************************
    /**
     * 环境参数
     * 温度补偿（实时温度修正）
     * -9℃ ~ 9℃ 整数位有效
     * 00H ~ 09H 代表  0℃ ~ 9℃
     * F7H ~ FFH 代表  -9℃ ~ -1℃
     * @param temp 修正温度的值 范围: -9 ~ 9
     * [temp]:(小 ---->> 大)
     * -9 ==> F7    -8 ==> F8    -7 ==> F9    -6 ==> FA    -5 ==> FB    -4 ==> FC    -3 ==> FD    -2 ==> FE    -1 ==> FF
     *  0 ==> 00     1 ==> 01     2 ==> 02     3 ==> 03     4 ==> 04     5 ==> 05     6 ==> 06     7 ==> 07     8 ==> 08    9 ==> 09
     */
    fun temperatureOffset(address: Byte, temp: Int): ByteArray{
        val pushMsg = createSingleWriteCommand(address ,HLR_OFFSET_TEMP_ENVIRONMENT)
        pushMsg[4] = 0x00
        pushMsg[5] = temp.to2ByteL()[0]
        return crcCheck(pushMsg)
    }




//***面板辅助数据（被动）*********************************************************************************************************************

    /**
     * 设置空调继电器的控制模式
     * (空调的优先级高)
     * @param address 设备地址
     * @param mode    控制模式  0:无效  1:自控  2:被控
     * @param relay   继电器    1:一路双线阀或一路三线阀（一控）默认
     *                         2:一路三线阀（二控）
     *                         3:两路双线阀或一路三线阀（一控）
     */
    fun setAirRelayControlMode(address: Byte,mode:Int ,relay:Int): ByteArray{
        val pushMsg = createSingleWriteCommand(address ,HLR_RELAY_AIR_PANEL)
        pushMsg[4] = mode.to2ByteL()[0]
        if (mode == 0){
            pushMsg[5] = 0x00
        }else{
            pushMsg[5] = relay.to2ByteL()[0]
        }
        return crcCheck(pushMsg)
    }


    /**
     * 设置地暖继电器的控制模式
     * (地暖的优先级低)
     * @param address 设备地址
     * @param mode    控制模式  0:无效  1:自控  2:被控
     * @param relay   继电器    1:一路双线阀或一路三线阀（一控）默认
     *                         2:一路三线阀（二控）
     *
     * 注：当空调继电器寄存器的低 8 位数据为 01 时，该
     * 寄存器低 8 位数据无法配置成 02；
     * 当空调继电器寄存器的低 8 位数据为 02 或 03 时，
     * 该寄存器数据无效
     */
    fun setFloorRelayControlMode(address: Byte,mode:Int ,relay:Int): ByteArray{
        val pushMsg = createSingleWriteCommand(address ,HLR_RELAY_FLOOR_PANEL)
        pushMsg[4] = mode.to2ByteL()[0]
        if (mode == 0){
            pushMsg[5] = 0x00
        }else{
            pushMsg[5] = relay.to2ByteL()[0]
        }
        return crcCheck(pushMsg)
    }



    /**
     * 设置新风继电器的控制模式
     * (新风的优先级低)
     * @param address 设备地址
     * @param mode    控制模式  0:无效  1:有效
     * 注：当 空调继电器 无效时 ,新风继电器才有效
     */
    fun setWindRelayControlMode(address: Byte,mode:Int): ByteArray{
        val pushMsg = createSingleWriteCommand(address ,HLR_RELAY_WIND_PANEL)
        val result = mode.to2ByteH()
        System.arraycopy(result, 0, pushMsg, 4, result.size)
        return crcCheck(pushMsg)
    }

    /**
     * 低温保护
     * @param temp
     * 0 ~ 5 对应 0℃ ~ 5℃
     * 15 无效（取消低温保护）
     */
    fun lowTemperatureProtection(address: Byte,temp:Int): ByteArray{
        val pushMsg = createSingleWriteCommand(address ,HLR_LOW_TEMP_DISC_PANEL)
        return if (temp in 0..5 || temp == 15){
            val result = temp.to2ByteH()
            System.arraycopy(result, 0, pushMsg, 4, result.size)
            crcCheck(pushMsg)
        }else{
            pushMsg
        }

    }


    /**
     * 面板是否上锁
     * @param isLock true:上锁   false:解锁(默认)
     */
    fun onOffLock(address: Byte,isLock:Boolean): ByteArray{
        val pushMsg = createSingleWriteCommand(address ,HLR_LOCK_PANEL)
        val result = if (isLock){
            1.to2ByteH()
        }else{
            0.to2ByteH()
        }
        System.arraycopy(result, 0, pushMsg, 4, result.size)
        return crcCheck(pushMsg)
    }

    /**
     * 上锁的模式
     * @param isFullLock true:全锁，锁定面板时锁定开关键   false:半锁，锁定面板时不锁开关键（默认）
     */
    fun lockMode(address: Byte,isFullLock:Boolean): ByteArray{
        val pushMsg = createSingleWriteCommand(address ,HLR_LOCK_MODE_PANEL)
        val result = if (isFullLock){
            1.to2ByteH()
        }else{
            0.to2ByteH()
        }
        System.arraycopy(result, 0, pushMsg, 4, result.size)
        return crcCheck(pushMsg)
    }

    /**
     * 数据上报模式
     * @param isMain true:主动上报    false:被动上报
     */
    fun dataReportMain(address: Byte,isMain:Boolean): ByteArray{
        val pushMsg = createSingleWriteCommand(address ,HLR_DATA_REPORT_PANEL)
        val result = if (isMain){
            0.to2ByteH()
        }else{
            1.to2ByteH()
        }
        System.arraycopy(result, 0, pushMsg, 4, result.size)
        return crcCheck(pushMsg)
    }

    /**
     * 按键指示灯亮度调节
     * @param mode  按键指示灯模式:  0:低亮模式4%   1:低亮模式为0
     * @param level 按键指示灯等级:范围:[0,6]
     *              0:自动（按键指示根据光照度反向自动调整以下等级）
     *              1:35%（按键）
     *              2:45%（按键）
     *              3:55%（按键）
     *              4:65%（按键）
     *              5:75%（按键）
     *              6:85%（按键）
     */
    fun  keyLampLevel(address: Byte, mode:Int ,level:Int): ByteArray{
        val pushMsg = createSingleWriteCommand(address ,HLR_INDICATOR_LIGHTNESS_PANEL)
        pushMsg[4] = mode.to2ByteL()[0]
        pushMsg[5] = level.to2ByteL()[0]
        return crcCheck(pushMsg)
    }

    /**
     * 光照度设置
     * @param level 光照度等级1 ~ 6 , 从弱到强  范围:[1,6]
     */
    fun illuminanceLevel(address: Byte, level:Int): ByteArray{
        val pushMsg = createSingleWriteCommand(address ,HLR_LUX_LEVEL_PANEL)
        val result = level.to2ByteH()
        System.arraycopy(result ,0 ,pushMsg ,4 ,result.size)
        return crcCheck(pushMsg)
    }


    /**
     * 面板背光休眠（包括按键、显示小屏）
     * @param time 休眠时间
     *        0:30秒
     *        1:1分钟
     *        2:2分钟
     *        3:3分钟
     *        4:4分钟
     *        5:5分钟
     *        15:不休眠
     */
    fun sleepBacklight(address: Byte, time:Int): ByteArray{
        val pushMsg = createSingleWriteCommand(address ,HLR_LIGHT_SLEEP_PANEL)
        val result = time.to2ByteH()
        System.arraycopy(result ,0 ,pushMsg ,4 ,result.size)
        return crcCheck(pushMsg)
    }


    /**
     * 获取当前面板的版本
     */
    fun getPanelVersion(address: Byte):ByteArray{
        val pushMsg = createSingleReadCommand(address ,HLR_VERSION_PANEL)
        val result = 1.to2ByteH()
        System.arraycopy(result ,0 ,pushMsg ,4 ,result.size)
        return crcCheck(pushMsg)
    }


    /**
     * 获取当前寄存器的值
     * @param hlr 寄存器地址
     */
    fun getReadHLRCommand(address: Byte ,hlr:ByteArray):ByteArray{
        val pushMsg = createSingleReadCommand(address ,hlr)
        val result = 1.to2ByteH()
        System.arraycopy(result ,0 ,pushMsg ,4 ,result.size)
        return crcCheck(pushMsg)
    }
}